package com.dimao.certificate_build_service.http.kotiln

import com.dimao.certificate_build_service.http.Api
import com.dimao.certificate_build_service.http.FailedReply
import com.dimao.certificate_build_service.http.SucceededReply
import com.dimao.certificate_build_service.pdf.kotiln.PDFBuildQueue
import io.vertx.core.json.JsonArray
import io.vertx.core.json.JsonObject
import io.vertx.ext.web.RoutingContext
import io.vertx.kotlin.coroutines.awaitResult
import io.vertx.kotlin.coroutines.dispatcher
import kotlinx.coroutines.*

class AddToPDFBuildQueueApi : Api, AsyncApi<Unit> {
    override fun run(context: RoutingContext?) {
        GlobalScope.launch (context!!.vertx().dispatcher()) { asyncRun(context) }
                .invokeOnCompletion {
                    context.response().putHeader("Content-Type", "application/json; charset=UTF-8")
                    if(it != null)
                        context.response().end(
                                FailedReply(it)
                                        .toJson()
                                        .toBuffer()
                        )
                    else context.response().end(
                            SucceededReply("添加到PDF生成队列成功")
                                    .toJson()
                                    .toBuffer()
                    )
                }
    }

    override suspend fun asyncRun(context: RoutingContext) = coroutineScope {
        val jsonArray = JsonArray(context.bodyAsString)
        val publisher = context.vertx()
                .eventBus()
                .publisher<JsonObject>(PDFBuildQueue.consumerName)

        try {
            var i = 0
            val futureList = ArrayList<Deferred<Void>>(jsonArray.size())
            while (i < jsonArray.size()){
                if(!publisher.writeQueueFull()){
                    futureList.add(async {
                        awaitResult<Void> { h ->
                            publisher.write(jsonArray.getJsonObject(i), h)
                        }
                    })
                    i++
                }
            }

            futureList.forEach{ future -> future.await() }
        }finally {
            publisher.close()
        }
    }
}